package com.fingard.dsp.bank.directbank.baidu11;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.baidu11.util.DESedeCoder;
import com.fingard.dsp.bank.directbank.baidu11.util.MD5Make;
import com.fingard.dsp.bank.directbank.baidu11.util.MD5Tool;
import com.fingard.dsp.bank.directbank.bankInterface.IBatRecRefund;
import com.fingard.dsp.bank.reqrespobj.batrecrefund.ReqBatRecRefund;
import com.fingard.dsp.bank.reqrespobj.batrecrefund.ReqQryBatRecRefund;
import com.fingard.dsp.bank.reqrespobj.batrecrefund.RetAtsBatRecRefund;
import com.fingard.dsp.bank.reqrespobj.batrecrefund.RetAtsQryBatRecRefund;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.util.ZipHelper;

public class BaiDu11BatRecRefund extends BaiDu11Base implements IBatRecRefund {
	/**
	 * 退保提交
	 * 
	 * 参考文档：百度保险直连平台文件接口说明-20161213-v1.3.docx
	 * 参考接口： 3.5.	退保回款文件(打款通知)
	 * 
	 * 文件命名规则(一天只支持一批)
	 * surrender_payment_yyyyMMdd.txt
	 * surrender_payment_yyyyMMdd.md5
	 * surrender_payment_yyyyMMdd.zip
	 * 
	 * 文件内容
	 * 第一行:
	 * 文件中交易笔数|文件中申请总金额|文件中实际打款总额|手续费总额
	 * 其他行：
	 * 百度用户ID|订单号|退保订单号|保单号|申请金额|实际打款金额|手续费|保单收益|打款到账的银行卡号|打款银行渠道编码
	 */
	@Override
	public RetAtsBatRecRefund submitBatRecRefund(ReqBatRecRefund p_reqBatRef) throws Exception {
		RetAtsBatRecRefund retAts = new RetAtsBatRecRefund(p_reqBatRef.reqHeader);

		SftpPortClient sftpPortClient = null;
		
		try {
			// 退保文件内容
			StringBuilder sbFileContent = new StringBuilder();

			String totalApplyAmt = p_reqBatRef.totalApplyAmt;
			if (StringHelper.hasAnyChar(totalApplyAmt)) {
				totalApplyAmt = StringHelper.amountMultiply100(totalApplyAmt);
			}
			String totalAmt = p_reqBatRef.totalAmt;
			if (StringHelper.hasAnyChar(totalAmt)) {
				totalAmt = StringHelper.amountMultiply100(totalAmt);
			}
			String totalFee = p_reqBatRef.totalFee;
			if (StringHelper.hasAnyChar(totalFee)) {
				totalFee = StringHelper.amountMultiply100(totalFee);
			}
			
			// 汇总信息: 文件中交易笔数|文件中申请总金额|文件中实际打款总额|手续费总额
			String tmpReqHeader = MessageFormat.format("{0}|{1}|{2}|{3}\r\n", p_reqBatRef.totalNum, totalApplyAmt, totalAmt, totalFee);
			sbFileContent.append(tmpReqHeader);

			// 流水号映射文件内容
			StringBuilder seqNoMappingContent = new StringBuilder();
			while (p_reqBatRef.readRecord()) {
				if (seqNoMappingContent.length() > 0) {
					seqNoMappingContent.append("\r\n");
				}
				
				String userId = p_reqBatRef.readedDetail.userId;
				String orderId = p_reqBatRef.readedDetail.oriOppOrderNo;
				String refundId = p_reqBatRef.readedDetail.refundNo;
				String srcNoteCode = p_reqBatRef.readedDetail.srcNoteCode;
				String applyAmt = p_reqBatRef.readedDetail.applyAmt;
				if (StringHelper.hasAnyChar(applyAmt)) {
					applyAmt = StringHelper.amountMultiply100(applyAmt);
				}
				String payAmt = p_reqBatRef.readedDetail.payAmount;
				if (StringHelper.hasAnyChar(payAmt)) {
					payAmt = StringHelper.amountMultiply100(payAmt);
				}
				String fee = p_reqBatRef.readedDetail.fee;
				if (StringHelper.hasAnyChar(fee)) {
					fee = StringHelper.amountMultiply100(fee);
				}
				String profit = p_reqBatRef.readedDetail.profit;
				if (StringHelper.hasAnyChar(profit)) {
					profit = StringHelper.amountMultiply100(profit);
				}
				String recAct = p_reqBatRef.readedDetail.recAct;
				if (StringHelper.hasAnyChar(recAct)) {
					String desKey = getBankConfig().getValueAsString("desKey");
					recAct = DESedeCoder.encryptData(recAct,desKey);
				}
				String recBankCode = getBankConfig().getMapValueByKey("bankCodeMapping", p_reqBatRef.readedDetail.recBankCode);
				
				// 每笔明细：百度用户ID|订单号|退保订单号|保单号|申请金额|实际打款金额|手续费|保单收益|打款到账的银行卡号|打款银行渠道编码
				String tmpReqBodyDetail = MessageFormat.format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}\r\n", 
						userId, orderId, refundId, srcNoteCode, applyAmt, payAmt, fee, profit, recAct, recBankCode);
				sbFileContent.append(tmpReqBodyDetail);
				
				seqNoMappingContent.append(p_reqBatRef.readedDetail.askNumber).append(",").append(refundId);
			}
			WriteBankLogLn2("本地退保文件内容:\r\n" + sbFileContent.toString());
			
			// 生成待上传文件并写入内容
			String refundFileDir = getRefundFileDirectory();
			Date tmpDateNow = new Date();
			String refundFileName = "surrender_payment_" + Format.Date8Format.format(tmpDateNow);
			String localRefundFilePath = refundFileDir + File.separator + refundFileName + ".txt";
			WriteBankLogLn2("本地退保文件路径: " + localRefundFilePath);
			
			File localRefundFile = new File(localRefundFilePath);
			if (localRefundFile.exists()) {
				retAts.respCode = "0";
				retAts.respInfo = "批次文件已上传，请勿重复上传!";
				retAts.transState = "BatchFailed";
				retAts.payInfoCode = "RepeatUpload";
				retAts.writeRetToATS();
				return retAts;
			}
			FileHelper.writeFile(localRefundFilePath, sbFileContent.toString(), getCharset());
			
			// 退保流水映射存入本地
			WriteBankLogLn2("本地退保流水映射文件内容:\r\n" + seqNoMappingContent.toString());
			String refundSeqNoPath = getDataFileDirectory(tmpDateNow) + File.separator + p_reqBatRef.reqBatchNO + ".txt";
			WriteBankLogLn2("本地退保流水映射文件路径:" + refundSeqNoPath);
			FileHelper.writeFile(refundSeqNoPath, seqNoMappingContent.toString(), getCharset());
			
			MD5Tool tMD5Tool = new MD5Tool();
			String fileMd5Value = MD5Make.getFileMD5String(localRefundFilePath);//对文件内容做第一次加密
			String salt = getBankConfig().getValueAsString("md5Salt");
			String contentMD5 = tMD5Tool.getStrMD(salt+fileMd5Value);//对加密后的文件加上密钥做第二次加密
			
			String fileMd5Path = refundFileDir + File.separator + refundFileName + ".md5";
			WriteBankLogLn2("本机MD5文件路径: " + fileMd5Path);
			FileHelper.writeFile(fileMd5Path, contentMD5, getCharset());
			
			// 压缩文件
			List<File> fileList = new ArrayList<File>();
			fileList.add(new File(localRefundFilePath));
			fileList.add(new File(fileMd5Path));
			String localRefundZipFilePath = refundFileDir + File.separator + refundFileName + ".zip";
			WriteBankLogLn2("本地退保文件压缩包路径: " + localRefundZipFilePath);
			FileOutputStream fos = new FileOutputStream(new File(localRefundZipFilePath));
			ZipHelper.toZip(fileList, fos);

			// 上传退保文件
			FtpSet ftpSet = bankFront.getFtpSet("refund_upload");
			sftpPortClient = new SftpPortClient(ftpSet);
			String  directDir = "";
			String tmpDate = Format.Date8Format.format(tmpDateNow);
			if (ftpSet.upDir.endsWith("/")) {
				directDir = tmpDate;
			} else {
				directDir = "/" + tmpDate;
			}
			String sftpFilePath = StringHelper.trimEnd(ftpSet.upDir, "/") + "/" + tmpDate + "/" + refundFileName + ".zip";
			WriteBankLogLn2("SFTP服务器压缩文件上传路径:" + sftpFilePath);
			FtpReceiver ftpReceiver = sftpPortClient.uploadFile(directDir, localRefundZipFilePath, sftpFilePath);

			retAts.respCode = "0";
			retAts.reqSeqID = p_reqBatRef.reqBatchNO;
			if (ftpReceiver.isCompleted) {
				retAts.respInfo = "上传成功";
				retAts.transState = "Uploaded";
				retAts.payInfoCode = "I4001";
			} else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
				retAts.respInfo = "上传通讯失败";
				retAts.transState = "BatchFailed";
				retAts.payInfoCode = "E9999";
			} else {
				retAts.respCode = "-1";
				retAts.respInfo = ftpReceiver.connMsg;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.respCode = "-1";
			retAts.respInfo = ex.toString();
			WriteBankLogLn(ex);
		} finally{
    		if(sftpPortClient != null){
    			try {
					sftpPortClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
					WriteBankLogLn(e);
				}
    		}
    	}

		if ("-1".equals(retAts.respCode) && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
			retAts.reqSeqID = p_reqBatRef.reqBatchNO;
		}
		
		retAts.writeRetToATS();
		return retAts;
	}

	/**
	 * 百度退保结果不通过查询接口主动查询，而是采用通知接口异步获取
	 */
	@Override
	public RetAtsQryBatRecRefund queryBatRecRefund(ReqQryBatRecRefund p_reqQryBatRef) throws Exception {
		RetAtsQryBatRecRefund retAts = new RetAtsQryBatRecRefund(p_reqQryBatRef.reqHeader);
		retAts.reqSeqID = p_reqQryBatRef.reqBatchNO;
		retAts.respCode = "-1";
		retAts.respInfo = "不支持的交易类型:" + p_reqQryBatRef.reqHeader.transType;
		retAts.writeAfterDetail();
		return retAts;
	}
}
